/*
	Scheduler
	Created: 2012-04-13 sam.huang
*/

var Scheduler = Scheduler || {/*time-task*/pointTasks:null,triggers:null};
Scheduler.triggers = {};
Scheduler.TRIGGER_MODE_DURATION = "TRIGGER_MODE_DURATION";//在一段时间区段内触发
Scheduler.TRIGGER_MODE_POINT = "TRIGGER_MODE_POINT";//在某个时间点触发

Scheduler.pointTasks = {};
Scheduler.oldPointTasks = {};//已执行的点任务
Scheduler.eventsLastTriggerTime = {};
Scheduler.TRIGGER_HITPOINT_ACCURACY = 200;//命中精度，毫秒（目的：对于时间点触发的任务，轮询时间必须小于该值）

Scheduler.OUTOFTIME_MODE_IMMEDIATELY = 0;//立即执行
Scheduler.OUTOFTIME_MODE_NEWER = 1;//最新的执行

Scheduler.durationTasks = [];//按起始时间升序排列的区段任务集
Scheduler.oldDurationTasks = [];//已执行的区段任务


//|事件|任务集合

(function() {
	pointTasks = Scheduler.pointTasks;
	oldPointTasks = Scheduler.oldPointTasks;
	triggers = Scheduler.triggers;
	lastTrgTime = Scheduler.eventsLastTriggerTime;
	
	durationTasks = Scheduler.durationTasks;
	oldDurationTasks = Scheduler.oldDurationTasks;
	
	/*
	 * 请求所有任务
	 * 
	 */
	Scheduler.requestTask = function(time) {
		//debug("[scheduler] request time:" + time + "->" + point(time));
		Scheduler.requestDurationTask(time);
		Scheduler.requestPointTask(time);
	};
	
	/*bool*/ Scheduler.requestPointTask = function(value) {
		var tasks = findPointTasks(point(value));
		if(!tasks)return;
		debug("[scheduler] requestPointTask("+point(value)+"), tasks:", tasks);
		for(i in tasks){
			var task = tasks[i];
			executePointTask(task);
		}
		removePointTasks(point(value));
	};
	
	/*
	 * 请求区段任务
	 * 
	 */
	Scheduler.requestDurationTask = function(time) {
		var tasks = findDurationTasks(point(time));
//		debug("[scheduler][requestDurationTask] time:"+time+", findDurationTasks:", tasks);
		if(!tasks)return;
		for(i in tasks){
			var dTask = tasks[i];
			if(executable(dTask, point(time))){
				executeDurationTask(dTask);
			}
		}
	};
	
	/*
	 * 删除区段任务 
	 * 
	 * 
	 */
	Scheduler.removeDurationTask = function(compareFun, data) {
		for(var i in durationTasks){
			if(compareFun(durationTasks[i].data, data)){
				info("[scheduler] delete duration task:", durationTasks[i]);
				durationTasks.splice(i,1);
				return true;
			}
		}
		return false;
	};
	
	/*
	 * 删除点任务 
	 * 
	 * 
	 */
	Scheduler.removePointTask = function(compareFun, data) {
		for(var item in pointTasks){
			var tasks = pointTasks[item];
			for(var i in tasks){
				if(compareFun(tasks[i].data, data)){
					info("[scheduler] delete task:", tasks[i]);
					tasks.splice(i,1);
					return true;
				}
			}
		}
		info("[scheduler] no task to delete:", data);
		return false;
	};
	
	/*task*/Scheduler.addPointTask = function(event, time, data) {
		var task = createTask(point(time), event, data);
		pushTask(point(time), task);
		info("[scheduler] append task("+task.event+"):", task);
		return task;
	};
	
	/*task*/Scheduler.addDurationTask = function(startValue, endValue, event, data) {
		if(isNaN(endValue) || endValue < startValue) endValue = startValue;
		var task = createDurationTask(point(startValue), point(endValue), event, data);
		loadDurationTask(task);
		info("[scheduler] append a duration task:", task);
		return task;
	};
	
	Scheduler.outOfTimeRevise = function(task, playedTime, mode){
		if(task.point < point(playedTime)){
			info("[scheduler] data out of time("+task.point+"<"+point(playedTime)+"):", task);
			if(Scheduler.OUTOFTIME_MODE_IMMEDIATELY == mode){
				executePointTask(task);
				removePointTaskByTask(task);
			}
		}
	};
	
	/*void*/ Scheduler.addEventHandler = function(/*string*/ event, /*function*/ handler) {
		if ("string" === typeof handler) {
			handler = new Function("event", handler);
		}
		if ("function" !== typeof handler) {
			error("[scheduler][addEventHandler] typeof handler：", handler);
			return;
		}
		triggers[event] = handler;
		lastTrgTime[event] = -1;
		info("[scheduler] add event handler：", handler);
	};

	/*void*/ Scheduler.start = function(interval, timeCallback) {
		if(interval == null || "undefined" == typeof interval)interval = 100;
		setInterval(function(){
			if(timeCallback){
				Scheduler.requestTask(timeCallback());
			}else{
				Scheduler.requestTask(new Date);
			}
		}, interval);
	};
	
	/*
	 * 删除区段任务 
	 * 
	 * 
	 */
	Scheduler.eachUndoneTaskData = function(fun) {
		for(var i in durationTasks){
			fun(durationTasks[i].data);
		}
		return false;
	};
	
	
	//--------------------------------------------------------------------------
	
	//装载区段任务
	function loadDurationTask(task){
		durationTasks.push(task);//这里默认数据按顺序装载
	}
	
	/*创建区段任务 DurationTask{"startPoint":startPoint, "endPoint":endPoint, "event":event, "data":data}*/
	function createDurationTask(startPoint, endPoint, event, data){
		return {"startPoint":startPoint, "endPoint":endPoint, "event":event, "data":data};
	}
	
	/*
	 * 1.查询过程中遇到已过期任务则删除（移入已执行列表）
	 * 
	 * @point 必须是按时间先后单向增长的数值（如当前时间）
	 * 注意：执行过的任务是否存在再次执行的可能
	 */
	function findDurationTasks(point){
		//TODO:加上上次point与当前point的大小检查，若变小则提示使用方法错误。
		var tasks = [];
		for(var i=0;i<durationTasks.length;i++){
			//TODO:已执行但还在区段内的任务是否查询？？添加执行标记，进行过滤。
			var dTask = durationTasks[i];
			if(dTask.startPoint > point){//任务开始时间未到，跳出循环（因为升序）
				break;
			}
			if(dTask.startPoint < point && dTask.endPoint < point){//过期的任务删除（直播暂停后再继续会出现过期数据）
				durationTasks.splice(i,1);
				debug("删除过期区段任务 （删除时point:"+point+"）:", dTask);
				continue;
			}
			if(isEffective(dTask, point))tasks.push(durationTasks[i]);//所有匹配任务
		}
		return tasks;
	}
	
	/*
	 * 执行区段任务
	 * 
	 */
	function executeDurationTask(task){
		triggers[task.event](task.data);
		oldDurationTasks.push(task);
		removeDurationTask(task);
		info("!![scheduler] execute duration task:", task);
		return true;
	}
	
	function removeDurationTask(task){
		for(var i=0;i<durationTasks.length;i++){
			var dTask = durationTasks[i];
			if(task == dTask){
				durationTasks.splice(i,1);
				return true;
			}
		}
	}
	
	/*
	 * 区段任务匹配
	 * 
	 */
	function isEffective(durationTask, point){
		return true;
	}
	
	/*
	 * 区段任务
	 */
	function executable(durationTask, point){
		return true;
	}
	
	/*Task{"point":point, "event":event, "data":data}*/
	function createTask(point, event, data){
		return {"point":point, "event":event, "data":data};
	}
	
	/*task|undefined*/ var findPointTasks = function(point) {
		return pointTasks[point];
	};
	
	/*void*/ var pushTask = function(point, task){
		var tasks = findPointTasks(point);
		if(!tasks){
			tasks=[];
			pointTasks[point] = tasks;
		}
		tasks.push(task);
	};
	
	/*void*/ var executePointTask = function(pointTask){
		triggers[pointTask.event](pointTask.data);
		lastTrgTime[pointTask.event] = pointTask.point;
		info("!![scheduler] execute point task:", pointTask);
	};
	
	/*void*/function removePointTasks(point){
		delete pointTasks[point];
		info("[scheduler] delete point tasks:", point);
	}
	
	/*boolean*/removePointTaskByTask = function(pointTask) {
			var tasks = pointTasks[pointTask.point];
			for(var i in tasks){
				if(tasks[i] == pointTask){
					info("[scheduler] delete point task:", tasks[i]);
					tasks.splice(i,1);
					return true;
				}
			}
		return false;
	};
	
	function point(value){
		var point = normalize(value);
		return point;
	}
	
	//ms为单位为毫秒的整数
	function normalize(ms){
		if(isNaN(ms) ){
			error("[scheduler][normalize()] ms is not a number :" + ms);
			return ms;
		}
		var st = Math.floor(ms/100);//取整，即截取到100毫秒
		return revieNum(st)/10;
	}
	
	//修正整数：末位数遇0、2、4、6、8时加1
	function revieNum(num){
		var st = String(num);
		var n =	st.substr(st.length-1, 1);
		switch(n){
			case "0": //执行case 8
			case "2": //执行case 8
			case "4": //执行case 8
			case "6": //执行case 8
			case "8": st = Number(st)+1; break;
			default: ;
		}
		return st;
	}
	

})();